#include "bw_FileHandler.h"
#include "bw_FcgiRequest.h"
#include "bw_Sqlite.h"
#include "bw_dbcol.h"
#include "cJSON.h"
#include "bw_public.h"
#include "public.h"
#include "bw_jskey.h"
#include "bw_JsonParse.h"
#include "bw_Str.h"
#include "bw_Upgrade.h"
#include "bw_file_tool.h"

using namespace bwcgi;
#define 	MIME_FORM_DATA	"multipart/form-data;"

extern char g_outbuf[];

static std::string respStr;

std::string gen_guid() 
{
	char cmd_buf[256]={0};
	snprintf(cmd_buf,sizeof(cmd_buf),"%s/%s",FCGI_module_folder(),BWENC_DATABASE);
	//BWSqlite db(BWENC_DATABASE);
	BWSqlite db(cmd_buf);
	
	char sql[SZ_1K] = { '\0' };
	snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES ('%s')",
	DBTBL_UUID, DBCOL_DES, "1");

	if (SQLITE_OK != db.Exec(sql)) {
		return "";
	}

	snprintf(sql, sizeof(sql),
			"SELECT rowid FROM %s order by rowid desc limit 1 offset 0",
			DBTBL_UUID);

	BWRow row = db.QueryRow(sql);
	if (row.empty()) {
		return "";
	}

	return row["rowid"];
}

// 图片文件上传
const char* bwenc_http_imgup(FcgiRequest* pFcgiReq) 
{
	cJSON *pout_root = NULL;
	cJSON *p_obj = NULL;
	char* str = NULL;
	int ret= 0;
	char cmd_buf[100] = { 0 };
	eENC_ERROR code = BWENC_ERROR_UNKNOW;

	cgi_debug("mimetype:%s", pFcgiReq->getMimetype());
	cgi_debug("bufferlen:%d", pFcgiReq->getBodyLen());

	char result[SZ_2K];
	snprintf(result, sizeof(result), "upload file:%s, filesize:%d",
			pFcgiReq->getUploadfile(), pFcgiReq->getUploadfileLen());
	cgi_debug("%s", result);

	if ((0 == strcmp(pFcgiReq->getUploadfile(), ""))
			|| (0 == pFcgiReq->getUploadfileLen())) {
		code = BWENC_ERROR_UNKNOW;
		return bwenc_common_ack(code);
	}

	const char* pos = strrchr(pFcgiReq->getUploadfile(), '.');
	std::string fileExt(pos + 1);
	std::transform(fileExt.begin(), fileExt.end(), fileExt.begin(), ::tolower);

	cgi_debug("fileExt:%s", fileExt.c_str());

	if (0 != fileExt.compare("gif") && 0 != fileExt.compare("jpg") && 0 != fileExt.compare("jpeg") && 0 != fileExt.compare("png") && 0 != fileExt.compare("bmp")) 
	{
		code = BWENC_ERROR_INVALID_IMG;
		return bwenc_common_ack(code);
	}
	std::string uuid = gen_guid();
	if (0 == uuid.compare("")) 
	{
		cgi_debug("gen uuid error");
		return bwenc_common_ack(code);
	}
	char filename[50] = { '\0' };
	sprintf(filename, "img/%lld_%s.%s", enc_gettime_ms(), uuid.c_str(), fileExt.c_str());
	cgi_debug("%s",filename);

	sprintf(cmd_buf, "mv %s %s/../%s/%s", pFcgiReq->getUploadfile(), FCGI_module_folder(),BWENC_WEBFILE,filename);
	ret = system(cmd_buf);
	if(ret != 0)
	{
		code = BWENC_ERROR_UNKNOW;
		goto error;
	}

	// 返回的json
	pout_root = cJSON_CreateObject();
	cJSON_AddNumberToObject(pout_root, "retCode", 0);
	cJSON_AddStringToObject(pout_root, "retMsg", "SUCCESS");
	p_obj = cJSON_CreateObject();
	cJSON_AddItemToObject(pout_root, "retData", p_obj);

	cJSON_AddStringToObject(p_obj, "file_url", filename);
	str = cJSON_PrintUnformatted(pout_root);
	memset(g_outbuf, 0, get_g_oubuf_size());
	memcpy(g_outbuf, str, strlen(str));
	free(str);

	cJSON_Delete(pout_root);
	return g_outbuf;
	
error:
	return bwenc_common_ack(code);
}

// 系统日志导出
const char* bwenc_http_logexport(FcgiRequest* pFcgiReq) {
	// 清空log目录
	char filename[FILE_NAME_LEN] = { '\0' };
	char cmd_buf[SZ_1K] = { '\0' };
	sprintf(cmd_buf,"rm -f %s/log/*", BWENC_WEBFILE);
	system(cmd_buf);

	// 用sqlite3命令导出CSV文件
	time_t now;
	struct tm *tm_now;
	time(&now);
	tm_now = localtime(&now);
	memset(cmd_buf, 0, sizeof(cmd_buf));
	sprintf(filename, "%s/log/log_%d%d%d%d%d.csv", BWENC_WEBFILE,
			tm_now->tm_year + 1900, tm_now->tm_mon + 1, tm_now->tm_mday,
			tm_now->tm_hour, tm_now->tm_min);
	sprintf(cmd_buf,"sqlite3 -header -csv %s \"select * from %s order by %s desc limit %d;\">%s",
	BWENC_DATABASE, DBTBL_LOG, DBCOL_ID,BWENC_OUT_LOG_NUM, filename);
	system(cmd_buf);
	pFcgiReq->enableDown();

	pFcgiReq->setDownloadfile(filename,NULL);

	return NULL;
}

// TODO 系统设置-配置导出
const char* bwenc_http_cfgexport(FcgiRequest* pFcgiReq) {
	return "";
}

// TODO 系统设置-配置导入
const char* bwenc_http_cfgimport(FcgiRequest* pFcgiReq) {
	return "";
}

// TODO 升级包上传请求地址
const char* bwenc_http_upgrade(FcgiRequest* pFcgiReq)
{
	cgi_debug("upgrade begin");
	if (!pFcgiReq || !pFcgiReq->getBody() || 0 == strlen(pFcgiReq->getBody())) {
		return nullptr;
	}

	string smime = pFcgiReq->getMimetype();
    cgi_debug("mime:%s", smime.c_str());
	if(smime.find(MIME_FORM_DATA) == string::npos)
	{
	    cgi_debug("plain content");
		const char *json = pFcgiReq->getBody();
		cgi_debug("[%s] [%s] request:\n%s", pFcgiReq->getRemoteAddr(),
				  pFcgiReq->getMethod(), json);

		if (strlen(json) == 0) {
			return bwenc_common_ack(BWENC_ERROR_INVALID_PARAM);
		}

		JsonParse jp(json);
		if (!jp.jsonValid()) {
//		cgi_debug("json valid");
			return bwenc_common_ack(BWENC_ERROR_INVALID_PARAM);
		}

		const char *mod = jp.getModule();
		const char *req = jp.getRequest();

		cgi_debug("mod=%s, req=%s", mod, req);
		if (BWStr::equals(mod, MOD_UPGRADE))
		{
			if (BWStr::equals(req, REQ_GET_FILECFG))
			{
				respStr.clear();
				respStr = getFileInfo();
				return respStr.c_str();
			}
			else if (BWStr::equals(req, REQ_SET_UPGCFG))
			{
				Enc_Upgrade *pSetUpgCfg = new Enc_Upgrade();
				eENC_ERROR code = pSetUpgCfg->setUpgCfg(json);
				SAFE_DELETE_PTR(pSetUpgCfg);
				return bwenc_common_ack(code);
			}
			else if (BWStr::equals(req, REQ_DOWNLOAD_UPGXML))
			{
				Enc_Upgrade * pDownloadXml = new Enc_Upgrade();
				eENC_ERROR code = pDownloadXml->downloadUpgXml(pFcgiReq);
				SAFE_DELETE_PTR(pDownloadXml);
				return bwenc_common_ack(code);
			}
			else if (BWStr::equals(req, REQ_GET_UPG_PROCESS))
			{
				respStr.clear();
				Enc_Upgrade * pGetProcess = new Enc_Upgrade();
				respStr = pGetProcess->getUpgProcess();
				SAFE_DELETE_PTR(pGetProcess);
				return respStr.c_str();
			}
			else if (BWStr::equals(req, REQ_GET_VERSIONS))
			{
                respStr.clear();
                Enc_Upgrade * pGetVersion = new Enc_Upgrade();
                respStr = pGetVersion->getVersions();
                SAFE_DELETE_PTR(pGetVersion);
                return respStr.c_str();
			}
			else if (BWStr::equals(req, REQ_STOP_UPGRADE))
            {
			    Enc_Upgrade * pStopUpgrade = new Enc_Upgrade();
			    eENC_ERROR code = pStopUpgrade->stopUpgProcess();
				SAFE_DELETE_PTR(pStopUpgrade);
				return bwenc_common_ack(code);
            }
		}
		return nullptr;
	}
	else
	{
        cgi_debug("bin content");
		string requestStr;
        requestStr.clear();
		if(pFcgiReq->getQuery(REQUEST_KEY))
            requestStr = pFcgiReq->getQuery(REQUEST_KEY);
		if(requestStr.empty())
		{
		    cgi_debug("requestStr is empty");
			return "";
		}
		else if( REQ_SIG_FILEINFO == requestStr )
		{
			respStr.clear();
			respStr = getFileMd5(pFcgiReq);
			return respStr.c_str();
		}
		else if( REQ_GET_ENCRYPTPKG == requestStr )
		{
			respStr.clear();
			respStr = getEncryptPkg(pFcgiReq);
			return respStr.c_str();
		}
		else if( REQ_BEGIN_UPGRADE == requestStr )
		{
			Upg_File::checkAndCreatePath(UPGPKG_TMPPATH);
			string upgTmpPkg = pFcgiReq->getUploadfile();
			size_t fnPos = upgTmpPkg.rfind('/');
			if(fnPos == string::npos)
				return bwenc_common_ack(BW_ERROR_UPGRADE_FILE);
			upgTmpPkg = UPGPKG_TMPPATH + upgTmpPkg.substr(fnPos+1);
//			cgi_debug("upg tmp pkg = %s", upgTmpPkg.c_str());
			if(!Upg_File::File_move(pFcgiReq->getUploadfile(), UPGPKG_TMPPATH))
			{
				cgi_debug("move file error : %s  --> %s", pFcgiReq->getUploadfile(), upgTmpPkg.c_str());
				return bwenc_common_ack(BW_ERROR_UPGRADE_FILE);
			}

			respStr.clear();
			Enc_Upgrade * pBeginUpgrade = new Enc_Upgrade();
			respStr = pBeginUpgrade->beginUpgrade(upgTmpPkg);
			SAFE_DELETE_PTR(pBeginUpgrade);
			return respStr.c_str();
		}
		return nullptr;
	}
}

// 统一清除系统上传的无用logo/二维码图片
int img_clean()
{
	char cmd_buf[256]={0};
	snprintf(cmd_buf,sizeof(cmd_buf),"%s/%s",FCGI_module_folder(),BWENC_DATABASE);
	//BWSqlite db(BWENC_DATABASE);
	BWSqlite db(cmd_buf);
	
	struct stat st;
	struct dirent *dir;
	char full_path[FILE_NAME_LEN + 260] = { '\0' };
	char part_path[FILE_NAME_LEN + 260] = { '\0' };
	char sql[SZ_1K] = { '\0' };

	// 1、遍历img文件夹
	char dirNew[FILE_NAME_LEN] = { '\0' };
	sprintf(dirNew, "%s/../%s/img/", FCGI_module_folder(),BWENC_WEBFILE);

	DIR* dirp = opendir(dirNew);
	if (!dirp) 
	{
		cgi_debug("open dir failed");
		return 0;
	}

	stENC_CHLSET* chl_info = NULL;
	stENC_OSDSET* osd_info = NULL;
	stENC_LOGOSET* logo_info = NULL;
	stENC_QRCODE* qr_info = NULL;
	char logo_url[MAX_PATH] = {'\0'};
	
	while ((dir = readdir(dirp)) != NULL) 
	{
		bool can_del = true;
		if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) 
		{
			continue;
		}

		sprintf(full_path, "%s%s", dirNew, dir->d_name);
		if (lstat(full_path, &st) == -1) 
		{
			continue;
		}

		sprintf(part_path, "/img/%s", dir->d_name);
		if (!S_ISDIR(st.st_mode)) 
		{   //S_ISDIR()宏判断是否是目录文件
			// 2、检查数据库logo_img、qrcode_set是否存在
			snprintf(sql, sizeof(sql), "select * from %s where %s='%s'",
			DBTBL_LOGO_IMG, DBCOL_PATH, part_path);
			BWRow row = db.QueryRow(sql);
			if (!row.empty()) 
			{
				can_del = false;
			}

			snprintf(sql, sizeof(sql), "select * from %s where %s='%s'",
			DBTBL_QRCODE_SET, DBCOL_PATH, part_path);
			row = db.QueryRow(sql);
			if (!row.empty()) 
			{
				can_del = false;
			}

			// 3、检查共享内存中osd是否在使用
			for (int i = 0; i < ENC_TOTAL_CHLMAX; i++) 
			{
				chl_info = &(g_encset_mst->enc_chls[i]);
				for (int j = 0; j < ENC_OSD_MAX_OVERLAY; j++) 
				{
					osd_info = &(chl_info->encchl_osd[j]);
					if (osd_info->osd_type == BWENC_OSD_TYPE_LOGO) 
					{
						logo_info = &(osd_info->osd_cfg.osd_logo);
						for (int k = 0; k < ENC_OSD_MAX_SLIDE_NUM; k++) 
						{
							sprintf(logo_url,"%s",logo_info->logo_url[k]);
							if (0== strcmp(logo_url,part_path)) 
							{
								can_del = false;
							}
						}
					} 
					else if (osd_info->osd_type == BWENC_OSD_TYPE_QRCODE) 
					{
						qr_info = &(osd_info->osd_cfg.osd_qr);
						sprintf(logo_url,"%s",qr_info->qr_url);
						if(0==strcmp(logo_url,part_path))
						{
							can_del = false;
						}
					}
				}
			}

			// 4、若2,3检查不存在则删除文件
			if(can_del)
			{
				// 删除文件
				remove(full_path);
			}

		}
	}

	closedir(dirp);
	return 1;
}

